#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import pexpect

from common.cleaner import clear
from common.util.cmd_utils import cmd_format
from generaldb.gbase8a.common.const import CmdStr


class SqlCmdTool:
    def __init__(self, os_user, db_user, db_pwd, timeout=30):
        self._timeout = timeout
        self._db_user = db_user
        self._db_pwd = db_pwd
        cmd = cmd_format(CmdStr.LOGIN_SQL, os_user, db_user)
        clear(db_user)
        self.child = pexpect.spawn(cmd, timeout=self._timeout)

    def run_sql_tool(self, *sql_cmd):
        """
        交互式运行sql命令
        :*sql_cmd: 以元组的方式依次传入sql命令
        """
        expect_code = 0
        create_socket_code = self.child.expect(["Enter password", pexpect.TIMEOUT, pexpect.EOF])
        if create_socket_code != expect_code:
            return False, ''
        self.child.sendline(s=self._db_pwd)
        clear(self._db_pwd)
        code = self.child.expect(["gbase>", pexpect.TIMEOUT, pexpect.EOF])
        if code != expect_code:
            return False, self.child.before.decode()
        for exe_cmd in sql_cmd:
            self.child.sendline(s=exe_cmd)
            code = self.child.expect([pexpect.EOF, pexpect.TIMEOUT, "rows in set", "row in set", "Query OK",
                                      "Unknown VC", "No VC selected"])
            if code in (0, 1):
                return False, "Failed execute sql cmd!"
            elif code in (2, 3):
                result = self.child.before.decode()
                return True, result
            elif code == 4:
                continue
            elif code == 5:
                return False, "VC ERROR"
            elif code == 6:
                return False, "VC NEEDED"
        return False, "Failed execute sql cmd!"

    def close_child(self):
        self.child.close()
